package com.bytz.modules.cms.common.excel;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.bytz.common.aspect.annotation.Dict;
import com.bytz.common.system.vo.DictModel;
import com.bytz.common.util.SpringContextUtils;
import com.bytz.modules.cms.common.exception.ExcelConvertNotFoundException;
import com.bytz.modules.system.service.ISysDictService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;

import java.util.*;
import java.util.stream.Collectors;

public class ExcelDictConvert implements Converter<String> {

    private final ISysDictService sysDictSvc = SpringContextUtils.getBean(ISysDictService.class);

    private String spilt;
    private Boolean hasSpilt = null;

    private Map<String, String> dictMap = new HashMap<>();
    private Map<String, String> dictTextMap = new HashMap<>();
    private List<DictModel> dictModels = new ArrayList<>();

    @Override
    public Class supportJavaTypeKey() {
        return null;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {

        return null;
    }

    //导入的时候文字转成字典项相对应key
    @Override
    public String convertToJavaData(ReadCellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {

        //获取注解
        Dict annotation = AnnotationUtils.findAnnotation(excelContentProperty.getField(), Dict.class);

        if (annotation == null) {

            return (String) cellData.getData();
        }

        return convertToDictKey(annotation, cellData);
    }

    //导出的时候转成字典key相对应的描述
    @Override
    public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {

        Dict annotation = AnnotationUtils.findAnnotation(contentProperty.getField(), Dict.class);

        if (annotation == null) {

            return null;
        }

        return convertToValue(annotation, value);

    }

    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext context) throws Exception {
        return Converter.super.convertToExcelData(context);
    }

    private WriteCellData<String> convertToValue(Dict annotation, String o) {

        initConvertData(annotation);

        List<String> dictValues = new ArrayList<>();

        WriteCellData<String> cellData = new WriteCellData<>();
        cellData.setType(CellDataTypeEnum.STRING);

        String v1 = String.valueOf(o);

        //有分隔符
        if (hasSpilt) {

            String[] dictItemValues = String.valueOf(o).split(spilt);

            Arrays.stream(dictItemValues).forEach(item -> {

                String value = dictTextMap.get(item);
                if (value == null) {

                    throw new ExcelConvertNotFoundException(String.format("未找到该【%s】值对应数据项，请检查输入数据", o));
                }

                dictValues.add(value);
            });

            cellData.setStringValue(StringUtils.join(dictValues, annotation.dictSplit()));
            return cellData;
        }

        //没有分隔符
        String value = dictTextMap.get(o);

        if (value == null) {

//            throw new ExcelConvertNotFoundException(String.format("未找到该【%s】值对应数据项，请检查输入数据", o));
            value = v1;
        }
        cellData.setStringValue(value);
        return cellData;
    }


    private String convertToDictKey(Dict annotation, CellData<String> cellData) {

        Object excelData = getCellData(cellData);

        List<String> dictKeys = new ArrayList<>();

        initConvertData(annotation);

        //有分隔符
        if (hasSpilt) {

            String[] dictItemValues = String.valueOf(excelData).split(spilt);

            Arrays.stream(dictItemValues).forEach(item -> {

                String key = dictMap.get(item);
                if (key == null) {

                    throw new ExcelConvertNotFoundException(String.format("未找到该【%s】值对应数据项，请检查输入数据", excelData));
                }

                dictKeys.add(key);
            });

            return StringUtils.join(dictKeys, annotation.dictSplit());
        }

        //没有分隔符
        String key = dictMap.get(excelData);

        if (key == null) {

            throw new ExcelConvertNotFoundException(String.format("未找到该【%s】值对应数据项，请检查输入数据", excelData));
        }

        return key;
    }

    private static Object getCellData(CellData cellData) {

        if (cellData.getType() == CellDataTypeEnum.STRING) {

            return cellData.getStringValue();
        }

        if (cellData.getType() == CellDataTypeEnum.NUMBER) {

            return cellData.getNumberValue();
        }

        return null;
    }

    private void initConvertData(Dict annotation) {

        if (dictModels.size() == 0) {

            dictModels = sysDictSvc.queryDictItemsByCode(annotation.dicCode());
            dictMap = dictModels.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue));
            dictTextMap = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText));
        }

        if (hasSpilt == null) {

            hasSpilt = StringUtils.isNotBlank(annotation.dictSplit());
            spilt = annotation.dictSplit();
        }
    }
}
